package net.tekool.projects.objscomp.commands;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import net.tekool.projects.objscomp.business.ClassDescriptor;

public class CreateDebugHTMLFile
{
	private ArrayList<ClassDescriptor> classes;
	private String html;
	private File debugDirFile;
	
	private static String DEBUG_TOKEN = "OBJS";
	private static String NEWLINE = System.getProperty("line.separator");
	
	private static final String HTML_DEBUG_FILE_NAME = "objs_debug.html";
	
	/**
	 * @param classes	The input classes list.
	 * @param html		The debug HTML file path to create.
	 */
	public CreateDebugHTMLFile(ArrayList<ClassDescriptor> classes, String html)
    {
	    super();
	    
	    this.classes = classes;
	    this.html = html;
    }
	
	/**
	 * Executes the command.
	 */
	public void execute()
	{
		String scriptTagsBlock = createScriptTagsList();
		String htmlFileContent = createHTMLDebugFileContent(scriptTagsBlock);
		createHTMLDebugFile(htmlFileContent);
	}
	
	//TODO We need to create specific command for it, it will be needed to empty DEBUG_TOKEN for release when src mode is not activated.
	private String createHTMLDebugFileContent(String scriptTagsBlock)
	{		
		File htmlFile = new File(html);

		FileReader reader;
		StringBuilder strBuild = new StringBuilder();
		try
		{
			reader = new FileReader(htmlFile);

			char[] buffer = new char[(int) htmlFile.length()];
			while(reader.read(buffer) != -1)
				;
			strBuild.append(buffer);

			reader.close();
		}
		catch(FileNotFoundException e)
		{
			throw (new Error(htmlFile.getPath() + " not found for reading"));
		}
		catch(IOException e)
		{
			throw (new Error("Error reading " + htmlFile.getPath()));
		}
		
		String htmlContent = strBuild.toString();

		String debugHTMLComment = "<!--" + DEBUG_TOKEN + "-->";

		String debugRegex = debugHTMLComment + "(.*)" + debugHTMLComment;
		Pattern debugPattern = Pattern.compile(debugRegex, Pattern.DOTALL|Pattern.UNIX_LINES);
		Matcher debugMatcher = debugPattern.matcher(htmlContent); 

		String htmlFileContent;
		String debugReplacement = debugHTMLComment + NEWLINE + scriptTagsBlock + debugHTMLComment;
		htmlFileContent = debugMatcher.replaceFirst(debugReplacement);
		
		return htmlFileContent;
	}
	
	/**
	* Create the debug HTML file and fill it with the generated debug HTML content.
	*/
	private void createHTMLDebugFile(String htmlFileContent)
	{		
		File htmlFile = new File(html);
		File htmlFileDirectory = htmlFile.getParentFile();
		File htmlDebugFile = new File(htmlFileDirectory, HTML_DEBUG_FILE_NAME);
		
		if(htmlDebugFile.exists())
			htmlDebugFile.delete();
		
		FileWriter writer;
		try
		{
			writer = new FileWriter(htmlDebugFile);
			writer.write(htmlFileContent);
			writer.close();
		}
		catch(FileNotFoundException e)
		{
			throw (new Error(htmlDebugFile.getPath() + " not found for writing"));
		}
		catch(IOException e)
		{
			throw (new Error("Error writing to " + htmlDebugFile.getPath()));
		}
		
		htmlDebugFile.setReadOnly();
	}

	/**
	* @returns The entire block made of scripts tags to insert in the debug HTML file.
	*/
	private String createScriptTagsList()
    {
		String scriptTagList = "";
		for( ClassDescriptor classDescriptor : classes )
			scriptTagList += "\t\t" + createTag(classDescriptor) + NEWLINE;
		
		return scriptTagList;
    }

	private String createTag( ClassDescriptor classDescriptor )
	{
		String filePath = "file:///" + classDescriptor.getFile().getAbsolutePath();
		String encodedFilePath = encodeFilePath(filePath);
		
		String tag = new String();
		tag += "<script type=\"text/javascript\" src=\"" + encodedFilePath + "\"></script>" ;

		return tag;
	}
	
	private String encodeFilePath( String filePath )
	{	
		String out = filePath;
		out = out.replace('\\', '/');
		out = out.replace(" ", "%20");
		return out;
	}
}